/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.support;

import java.io.Flushable;

/**
 * 这个类非常的重要，它是我们程序员对事务同步的扩展点：用于事务同步回调的接口，AbstractPlatformTransactionManager支持它。
 * <p>
 * 注意：自定义的同步器可以通过实现Ordered接口来自己定制化顺序，若没实现接口就按照添加的顺序执行~
 *
 * @author Juergen Hoeller
 * @see TransactionSynchronizationManager
 * @see AbstractPlatformTransactionManager
 * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
 * @since 02.06.2003
 */
public interface TransactionSynchronization extends Flushable {

	/**
	 * 正确提交时的完成状态。
	 */
	int STATUS_COMMITTED = 0;

	/**
	 * 正确回滚的情况下的完成状态。
	 */
	int STATUS_ROLLED_BACK = 1;

	/**
	 * 启发式混合完成或系统错误时的完成状态。
	 */
	int STATUS_UNKNOWN = 2;


	/**
	 * 事务赞提suspend的时候调用此方法
	 * 实现这个方法的目的一般是释放掉绑定的resources
	 *
	 * @see TransactionSynchronizationManager#unbindResource
	 */
	default void suspend( ) {
	}

	/**
	 * 事务恢复时候调用
	 *
	 * @see TransactionSynchronizationManager#bindResource
	 */
	default void resume( ) {
	}

	/**
	 * 将基础会话刷新到数据存储区（如果适用） 比如Hibernate/Jpa的session
	 *
	 * @see org.springframework.transaction.TransactionStatus#flush()
	 */
	@Override
	default void flush( ) {
	}

	/**
	 * 在事务提交之前促发。在 AbstractPlatformTransactionManager.processCommit 方法里 commit之前触发
	 * 事务提交之前，比如flushing SQL statements to the database
	 * 请注意：若此处发生了异常，会导致回滚
	 *
	 * @param readOnly whether the transaction is defined as read-only transaction
	 * @throws RuntimeException in case of errors; will be <b>propagated to the caller</b>
	 *                          (note: do not throw TransactionException subclasses here!)
	 * @see #beforeCompletion
	 */
	default void beforeCommit(boolean readOnly) {
	}

	/**
	 * 在beforeCommit之后，在commit/rollback之前执行
	 * 它和beforeCommit还有个非常大的区别是：即使beforeCommit抛出异常了  这个也会执行
	 *
	 * @throws RuntimeException in case of errors; will be <b>logged but not propagated</b>
	 *                          (note: do not throw TransactionException subclasses here!)
	 * @see #beforeCommit
	 * @see #afterCompletion
	 */
	default void beforeCompletion( ) {
	}

	/**
	 * 这个就非常重要了，它是事务提交（注意事务已经成功提交，数据库已经持久化完成这条数据了）后执行  注意此处是成功提交而没有异常
	 * javadoc说了：此处一般可以发短信或者email等操作~~因为事务已经成功提交了
	 * <p>
	 * =====但是但是但是：======
	 * 事务虽然已经提交，但事务资源（链接connection）可能仍然是活动的和可访问的。
	 * 因此，此时触发的任何数据访问代码仍将“参与”原始事务 允许执行一些清理（不再执行提交操作！）
	 * 除非它明确声明它需要在单独的事务中运行。
	 *
	 * @throws RuntimeException in case of errors; will be <b>propagated to the caller</b>
	 *                          (note: do not throw TransactionException subclasses here!)
	 */
	default void afterCommit( ) {
	}

	/**
	 * 和上面的区别在于：即使抛出异常回滚了  它也会执行的。它的notice同上
	 *
	 * @param status completion status according to the {@code STATUS_*} constants
	 * @throws RuntimeException in case of errors; will be <b>logged but not propagated</b>
	 *                          (note: do not throw TransactionException subclasses here!)
	 * @see #STATUS_COMMITTED
	 * @see #STATUS_ROLLED_BACK
	 * @see #STATUS_UNKNOWN
	 * @see #beforeCompletion
	 */
	default void afterCompletion(int status) {
	}

}
